package com.ruoyi.iot.config;

import com.google.common.base.Strings;
import com.ruoyi.base.service.IRoomService;
import com.ruoyi.data.domain.TdataHtWg;
import com.ruoyi.data.domain.TdataRtRs;
import com.ruoyi.data.domain.TdataRtRsDay;
import com.ruoyi.data.domain.TdataRtRsHour;
import com.ruoyi.data.domain.TdataRtWgc;
import com.ruoyi.data.service.ITdataHtEqService;
import com.ruoyi.data.service.ITdataHtWgService;
import com.ruoyi.data.service.ITdataRtRsService;
import com.ruoyi.data.service.ITdataRtWgcService;
import com.ruoyi.iot.IotContext;
import com.ruoyi.iot.client.NioClient;
import com.ruoyi.iot.client.PortClientCallback;
import com.ruoyi.iot.domain.CjqMeter;
import com.ruoyi.old.service.OldDataService;
import com.ruoyi.param.domain.TparamTp;
import com.ruoyi.param.service.ITparamEqService;
import com.ruoyi.param.service.ITparamTmService;
import com.ruoyi.param.service.ITparamTpService;
import com.ruoyi.param.service.ITparamUeService;
import com.ruoyi.param.utils.TpTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

@Component
@Slf4j
public class TaskConfig {

    @Autowired
    private IRoomService roomService;

    @Autowired
    private IotContext iotContext;

    @Autowired
    private ITparamEqService tParamEqService;

    @Autowired
    private ITparamTmService tParamTmService;

    @Autowired
    private ITparamTpService tParamTpService;

    @Autowired
    private ITparamUeService tParamUeService;

    @Autowired
    private ITdataHtEqService rtHtEqService;

    @Autowired
    private ITdataHtWgService htWgService;

    @Autowired
    private ITdataRtRsService rtRsService;

    @Autowired
    private ITdataRtWgcService rtWgcService;

    @Autowired
    private OldDataService oldDataService;

    @Scheduled(cron = "0 0 0 * * ?")
//    @Scheduled(cron = "0 0/5 * * * ?")
    public void callVaw() {
        log.info("callVaw");
        List<CjqMeter> cjqMeters = roomService.selectCjqMeterList(null);
        Map<String, List<TparamTp>> tParamTpMapList = tParamTpService.selectTpListByRoomIds(cjqMeters.stream().map(CjqMeter::getRoomId).collect(Collectors.toList()), 1).stream().collect(Collectors.groupingBy(TparamTp::getRoomId));

        List<TdataRtRs> tdataRtRsList = new ArrayList<>();
        for (CjqMeter cjqMeter : cjqMeters) {
            NioClient nioClient = iotContext.getNioClientMap().get(cjqMeter.getCjqNo());
            if (nioClient != null && !Strings.isNullOrEmpty(cjqMeter.getMeterNo())) {
                // 定时查询电压电流功率
//                nioClient.readTotalEnergy(Integer.valueOf(cjqMeter.getMeterNo()).byteValue(), new PortClientCallback() {
//                    @Override
//                    public void readTotalEnergy(BigDecimal totalW, BigDecimal positiveW, BigDecimal negativeW, BigDecimal v, BigDecimal a, BigDecimal w, BigDecimal factor, BigDecimal rate, BigDecimal reactiveW, BigDecimal apparentW) {
//
//                        tdataRtRsList.add(new TdataRtRs().setId(UUID.randomUUID().toString()).setRoomId(cjqMeter.getRoomId())
//                                .setLoopNo(1).setDt(LocalDateTime.now()).setVol(v).setCur(a).setYggl(w)
//                                .setStopReason(0).setRunStatus(1).setWorkStatus(null).setLoopEq(totalW));

                // 同步断电送电时段
                List<TparamTp> tparamTps = tParamTpMapList.get(cjqMeter.getRoomId());
                if (tparamTps != null && !tparamTps.isEmpty()) {
                    TparamTp tparamTp = tparamTps.get(0);
                    if (tparamTp != null) {
                        String[] time = TpTimeUtil.time(tparamTp);
                        if (!Strings.isNullOrEmpty(time[0]) && !Strings.isNullOrEmpty(time[1]) && tparamTp.getRunType() == 1) {
                            log.info("tParamTp " + tparamTp);
                            nioClient.writePeriods(Integer.valueOf(cjqMeter.getMeterNo()).byteValue(),
                                    Short.parseShort(time[2]), time[0], Short.parseShort(time[3]), time[1], null);
                        }
                    }
                }
//                    }
//                });
            }
        }
//        if (!tdataRtRsList.isEmpty()) {
//            rtRsService.insertList(tdataRtRsList);
//        }
    }

    @Scheduled(cron = "0 0/10 1-22 * * ? ")
    public void callWg() {
        log.info("callWg");
        List<CjqMeter> cjqMeters = roomService.selectCjqMeterList(null);
        for (CjqMeter cjqMeter : cjqMeters) {

            NioClient nioClient = iotContext.getNioClientMap().get(cjqMeter.getCjqNo());
            if (nioClient != null && !Strings.isNullOrEmpty(cjqMeter.getMeterNo())) {
                nioClient.readRelaysState(Integer.valueOf(cjqMeter.getMeterNo()).byteValue(), new PortClientCallback() {
                    // 继电器状态字 有恶性负载标志
                    @Override
                    public void readMalignantLoadState(int state) {
                        if (state == 1) {
                            wgRecord(nioClient, cjqMeter.getRoomId(), Integer.valueOf(cjqMeter.getMeterNo()), 0L);
                        }
                    }

                    // 继电器状态字 总功率超限标志
                    @Override
                    public void readTotalPowerState(int state) {
                        if (state == 1) {
                            wgRecord(nioClient, cjqMeter.getRoomId(), Integer.valueOf(cjqMeter.getMeterNo()), 1L);
                        }
                    }

                    // 继电器状态字 单次功率超限标志
                    @Override
                    public void readSinglePowerState(int state) {
                        if (state == 1) {
                            wgRecord(nioClient, cjqMeter.getRoomId(), Integer.valueOf(cjqMeter.getMeterNo()), 2L);
                        }
                    }
                });
            }
        }
    }

    private void wgRecord(NioClient nioClient, String roomId, Integer meterNo, Long wgReason) {
        TdataHtWg tdataHtWg = htWgService.selectTdataHtWg(roomId);
        if (tdataHtWg != null) {
            long wgTime = tdataHtWg.getWgDt().toEpochSecond(ZoneOffset.of("+8"));
            if (System.currentTimeMillis() / 1000 - wgTime > 10 * 60) {
                log.info("readTotalPowerState");
                nioClient.readTotalEnergy(meterNo.byteValue(), new PortClientCallback() {
                    @Override
                    public void readTotalEnergy(BigDecimal totalW, BigDecimal positiveW, BigDecimal negativeW, BigDecimal v, BigDecimal a, BigDecimal w, BigDecimal factor, BigDecimal rate, BigDecimal reactiveW, BigDecimal apparentW) {
                        htWgService.insert(new TdataHtWg().setId(UUID.randomUUID().toString()).setRoomId(roomId)
                                .setDt(LocalDateTime.now()).setWgDt(LocalDateTime.now()).setWgReason(wgReason).setWgPower(w)
                                .setRunStatus(1L)
                        );
                    }
                });

                if (rtWgcService.updateTimesByRoomId(roomId) == 0) {
                    rtWgcService.insert(new TdataRtWgc().setId(UUID.randomUUID().toString()).setRoomId(roomId)
                            .setDt(LocalDateTime.now()).setWgTimes(1).setRunStatus(1));
                }
            }
        }
    }

    @Scheduled(cron = "0 0 0/1 * * ?")
    public void dataUpdate() {
        log.info("dataUpdate");
        List<String> roomIds = roomService.selectAllOldRoomId();
        for (int i = 0; i < roomIds.size(); i += 100) {
            List<String> subList = roomIds.subList(i, Math.min((i + 100), roomIds.size()));
            tParamEqService.refresh(oldDataService.selectTodayParamEqList(subList));
            tParamTmService.refresh(oldDataService.selectTodayParamTmList(subList));
            tParamTpService.refresh(oldDataService.selectTodayParamTpList(subList));
            tParamUeService.refresh(oldDataService.selectTodayParamUeList(subList));
            rtHtEqService.refresh(oldDataService.selectTodayDataHtEqList(subList));
            htWgService.refresh(oldDataService.selectTodayDataHtWgList(subList));
            rtRsService.refresh(oldDataService.selectTodayDataRtRsList(subList));
            rtWgcService.refresh(oldDataService.selectTodayDataRtWgcList(subList));
        }
    }

    @Scheduled(cron = "0 0 3 * * ?")
    public void dayLoopEq() {
        log.info("dayLoopEq");
        List<TdataRtRsDay> insertRtRsDayList = new ArrayList<>();
        List<String> roomIds = roomService.selectAllRoomId();

        LocalDate yesterday = LocalDate.now().minusDays(1);
        List<TdataRtRs> tdataRtRsDay = rtRsService.selectRtRsDay(yesterday);

        for (String roomId : roomIds) {
            BigDecimal loopEq1 = BigDecimal.ZERO;
            for (TdataRtRs rtRs1 : tdataRtRsDay) {
                if (Objects.equals(rtRs1.getRoomId(), roomId) && rtRs1.getLoopEq().compareTo(loopEq1) > 0) {
                    loopEq1 = rtRs1.getLoopEq();
                }
            }

            if (loopEq1.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal loopEq2 = rtRsService.selectLoopEqByRoomIdDt(roomId, yesterday);
                if (loopEq2 == null) {
                    loopEq2 = BigDecimal.ZERO;
                }
                BigDecimal subtractEq = loopEq1.subtract(loopEq2);
                if (subtractEq.compareTo(BigDecimal.ZERO) > 0) {
                    insertRtRsDayList.add(new TdataRtRsDay().setId(UUID.randomUUID().toString()).setRoomId(roomId).setDt(yesterday)
                            .setLoopEq(subtractEq));
                }
            }
        }

        if (!insertRtRsDayList.isEmpty()) {
            rtRsService.insertRtRsDay(insertRtRsDayList);
        }
    }

    @Scheduled(cron = "0 5 0/1 * * ?")
    public void hourLoopEq() {
        log.info("hourLoopEq");
        List<TdataRtRsHour> insertRtRsDayList = new ArrayList<>();
        List<String> roomIds = roomService.selectAllRoomId();

        LocalDateTime localLastHour = LocalDateTime.now().minusHours(1);
        String lastHour = localLastHour.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
        List<TdataRtRs> tdataRtRsHour = rtRsService.selectRtRsHour(lastHour);

        for (String roomId : roomIds) {
            BigDecimal loopEq1 = BigDecimal.ZERO;
            for (TdataRtRs rtRs1 : tdataRtRsHour) {
                if (Objects.equals(rtRs1.getRoomId(), roomId) && rtRs1.getLoopEq().compareTo(loopEq1) > 0) {
                    loopEq1 = rtRs1.getLoopEq();
                }
            }

            if (loopEq1.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal loopEq2 = rtRsService.selectLoopEqByRoomIdDtTime(roomId, localLastHour);
                if (loopEq2 == null) {
                    loopEq2 = BigDecimal.ZERO;
                }
                BigDecimal subtractEq = loopEq1.subtract(loopEq2);
                if (subtractEq.compareTo(BigDecimal.ZERO) > 0) {
                    insertRtRsDayList.add(new TdataRtRsHour().setId(UUID.randomUUID().toString()).setRoomId(roomId).setDt(localLastHour)
                            .setLoopEq(subtractEq));
                }
            }
        }

        if (!insertRtRsDayList.isEmpty()) {
            rtRsService.insertRtRsHour(insertRtRsDayList);
        }
    }
}
